﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Threading = System.Threading;
using Microsoft.Forums.OfflineStore;
using System.Windows.Threading;
using Microsoft.Forums.ForumsProvider;
using System.IO;

namespace Microsoft.Forums.ForumsClient.Models
{
    /// <summary>
    /// A view model for the threaded view of MyThreads
    /// </summary>
    public class ThreadedMyThreadsViewModel : HierarchicalPostContainerModel, IFilterableModel
    {
        /// <summary>
        /// the user log on info
        /// </summary>
        UserLogOnInformation userLogonInfo;
        DetailedUser userInfo;

        /// <summary>
        ///  Get the user Filter Settings.
        /// </summary>
        public ThreadFilterSettings FilterSettings
        {
            get;
            private set;
        }

        /// <summary>
        /// Gets or sets the user.
        /// </summary>
        /// <value>The user.</value>
        public DetailedUser UserInfo
        {
            get
            {
                return userInfo;
            }
            private set
            {
                userInfo = value;
                OnPropertyChanged("UserInfo");
            }
        }


        /// <summary>
        /// Initializes a new instance of the <see cref="ThreadedMyThreadsViewModel"/> class.
        /// </summary>
        /// <param name="dispatcher">The dispatcher.</param>
        public ThreadedMyThreadsViewModel(UserLogOnInformation user, Dispatcher dispatcher)
            : base(dispatcher)
        {
            if (dispatcher == null) throw new ArgumentNullException("dispatcher", "dispatcher must not be null");
            if (user == null) throw new ArgumentNullException("user", "user must not be null");

            FilterSettings = new ThreadFilterSettings();
            userLogonInfo = user;
            UserInfo = user.UserInfo;

            userLogonInfo.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(userLogonInfo_PropertyChanged);
        }

        /// <summary>
        /// Handles the PropertyChanged event of the userLogonInfo control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.ComponentModel.PropertyChangedEventArgs"/> instance containing the event data.</param>
        void userLogonInfo_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            if (e.PropertyName.Equals("UserInfo"))
            {
                UserInfo = userLogonInfo.UserInfo;
                if (userInfo != null)
                {
                    UserInfo.UpdatedUserThread += new Action<Guid,Guid>(UserInfo_UpdatedUserThread);
                    PopulateRootPosts();
                }
            }
        }

        /// <summary>
        /// A thread has an update from the current user. Check if this model doesn have this thread in it
        /// yet and load it
        /// </summary>
        /// <param name="threadId">The threadId.</param>
        private void UserInfo_UpdatedUserThread(Guid forumId, Guid threadId)
        {
            if (rootPosts != null)
            {
                lock(rootPosts)
                {
                    if (!rootPosts.Any(p => p.Post.ThreadId == threadId))
                    {
                        Thread thread = ObjectRegistry.GetThread(forumId, threadId);
                        Post rootPost = ObjectRegistry.GetPost(forumId, (Guid)thread.RootPostId);

                        var postModel = new ThreadedPostViewModel(rootPost, DispatcherUI);
                        postModel.ThreadIfRootPost = thread;
                        rootPosts.Add(postModel);
                    }
                }
            }
        }

        /// <summary>
        /// Gets the root posts.
        /// </summary>
        /// <param name="store">The store.</param>
        /// <returns></returns>
        protected override IEnumerable<Post> GetRootPosts(ForumsOfflineStore store)
        {
            if (UserInfo == null) return null;
            var threadIds =
                from p in store.Posts
                where p.CreatedById == UserInfo.Id
                group p by p.ThreadId into th
                select th.Key;

            var ids = threadIds.ToList();
            var posts = from p in store.Posts
                        where p.ParentId == null && ids.Contains(p.ThreadId)
                        select p;

            return posts;
        }

        /// <summary>
        /// Returns a <see cref="System.String"/> that represents this instance.
        /// </summary>
        /// <returns>
        /// A <see cref="System.String"/> that represents this instance.
        /// </returns>
        public override string ToString()
        {
            if (UserInfo == null)
            {
                return String.Empty;
            }
            else
            {
                return UserInfo.DisplayName + "'s Threads";
            }
        }

    }
}
